package com.tedu.weibo.exception;

import com.tedu.weibo.result.JsonResult;
import com.tedu.weibo.result.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * 全局异常处理器
 * 1.要在当前类上添加注解@ControllerAdvice
 * 2.每个方法用于处理一个特定异常（相当于catch） 并且方法上要使用注解：@ExceptionHandler
 *
 * 这样一来一旦一个Controller处理某个请求的方法在处理过程中抛出了一个异常时
 * SpringMVC就会自动调用当前类中处理这个异常的方法
 * 即：抛出的异常与当前类中的方法上指定的异常类型匹配的方法
 * */
@Slf4j
@RestControllerAdvice
//使用RestControllerAdvice注解，就无需在每个方法上添加@ResponseBody注解，与@RestController道理一致
//@ControllerAdvice
public class GlobalExceptionHandler {
    /*
    相当于catch(RuntimeException e){}
    由于Controller处理用户请求的方法抛出了异常，那么就意味着该方法处理没有机会将处理结果返回给客户端，
    而是将异常的处理放在当前方法中进行处理，那么该方法此时需要返回一个JsonResult对象给客户端回复
    * */
    @ExceptionHandler
    public JsonResult doHandleRuntimeException(RuntimeException e){
        return new JsonResult(Status.OPERATION_ERROR,e.getMessage());
    }
    @ExceptionHandler
    public JsonResult doHandleIllegalArgumentException(IllegalArgumentException e){
        System.out.println("参数不合法");
        return new JsonResult(Status.OPERATION_ERROR,e.getMessage());
    }

    @ExceptionHandler
    //通常我们可以捕获一个范围较大的异常，避免因为出现一些为指定的异常导致没有响应的情况
    public JsonResult doHandleException(Exception e){
        log.error(e.getMessage(),e);
        return new JsonResult(Status.UNKNOWN_ERROR);
    }

    /*
    当验证框架在验证浏览器发送过来的数据时没有通过验证，此时会抛出如下异常
    * */
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        String message = e.getFieldError().getDefaultMessage();
        log.warn(message,e);
        return new JsonResult(Status.VALIDATE_FAILED,message);
    }
    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException e){
        String message = e.getMessage();
        message = message.substring(message.indexOf(":")+1).trim();
        log.warn(message,e);
        return new JsonResult(Status.VALIDATE_FAILED,message);
    }

}
